export default {
    // 防抖
    debounce(fun, delay = 500) {
        return function (args) {
            let that = this;
            let _args = args;
            clearTimeout(fun.id);
            fun.id = setTimeout(() => {
                fun.call(that, _args);
            }, delay);
        };
    },

    //节流：规定在一个单位时间内，只能触发一次函数。如果这个单位时间内触发多次函数，只有一次生效。
    throttle(fn, delay = 500) {
        let timer = true;
        return function (args) {
            let that = this;
            let _args = arguments;
            if (!timer) {
                return false;
            }
            timer = false;
            setTimeout(() => {
                fn.apply(that, _args);
                timer = true;
            }, delay);
        };
    },
    /**
     * 判断当前是不是一个函数 如果是就执行,
     * @param Fun
     * @param objFunc
     */

    isFunc(Fun, ...objFunc) {
        if (Fun instanceof Function) {
            Fun();
            if (Array.isArray(objFunc)) {
                for (let key in objFunc) {
                    objFunc[key] instanceof Function && objFunc[key]();
                }
            }
        }
    },

    /**
     * 匹配字符中是否存在多个http地址
     * @param {String}} str
     * 返回一个对象 true 为一个 false 为个
     */
    MatchingProtocol(str) {
        if (!str) return false;
        const regex = /http:/g;
        const result = str.match(regex) === null ? str.match(/https:/g) : str.match(regex);
        // 当前连接里面只有一HTTP或者HTTPS，返回true 否则返回false 在返回当前的图片
        return {
            many: result && result.length === 1 ? true : false,
            list: result,
        };
    },
    /**
     * 倒计时
     * @param item 倒计时时间
     * @param running 正在倒计时中得会执行得函数
     * @param finish 倒计时结束执行得函数
     */
    countDown(item = 60, running, finish) {
        let stop = setInterval(() => {
            if (item <= 0) {
                clearInterval(stop);
                running instanceof Function && running(stop, item);
                finish instanceof Function && finish(stop, item);
            } else {
                running instanceof Function && running(stop, item);
            }

            item--;
        }, 1000);
    },
    /**
     * 计算经纬度差值
     * @param {我当前经度} lat1
     * @param {我当前纬度} lng1
     * @param {企业的经度} lat2
     * @param {企业的纬度} lng2
     */
    positionToCalculate(lat1, lng1, lat2, lng2) {
        const Rad = (d) => {
            return (d * Math.PI) / 180.0; // 经纬度转换成三角函数中度分表形式。
        };
        let radLat1 = Rad(lat1);
        let radLat2 = Rad(lat2);
        let a = radLat1 - radLat2;
        let b = Rad(lng1) - Rad(lng2);
        let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * 6378.137; // EARTH_RADIUS;
        s = Math.round(s * 1000) / 1000; // 这里输出米   //输出为公里为 1Math.round(s * 10000) / 10000;
        let result = s
            .toString()
            .split(".")
            .map((i) => parseFloat(i));
        const [Km, M] = result;
        if (Km == null || Km === 0) {
            return M + "米";
        } else {
            return s + "公里";
        }
    },
    /**
     * 返回当前数据的数据类型
     * @param data 数据源
     * @returns
     */
    isType(data) {
        if (data === "") return "";
        switch (Object.prototype.toString.call(data)) {
            case "[object Object]":
                return "Object";
            case "[object Number]":
                return "Number";
            case "[object Array]":
                return "Array";
            case "[object Boolean]":
                return "Boolean";
            case "[object Null]":
                return "Null";
            case "[object Undefined]":
                return "Undefined";
            case "[object String]":
                return "String";
            case "[object Symbol]":
                return "Symbol";
            case "[object Date]":
                return "Date";
            case "[object BigInt]":
                return "BigInt";
            case "[object Function]":
                return "Function";
        }
    },
    /**
     * 判断当前数据源是否为空
     * @param { any }  数据源
     * @return { Boolean}
     */
    isNull(data) {
        const set = new Set(["", null, "null", undefined, "undefined"]);
        return set.has(data);
    },

    /**
     * 判断是否是 16 进制颜色
     */
    hexadecimal(color) {
        if (!isNull(color)) {
            const set = new Set(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "#"]),
                colorS = color.split(""),
                isList = [];
            //toUpperCase 小写转大写  toLowerCase大写转小写
            colorS.forEach((item) => {
                isList.push(set.has(item.toLowerCase()));
            });
            return isList.every((item) => item === true);
        }
    },
    // 防抖
    debounce(fun, delay = 500) {
        return function (args) {
            let that = this;
            let _args = args;
            clearTimeout(fun.id);
            fun.id = setTimeout(() => {
                fun.call(that, _args);
            }, delay);
        };
    },

    /***
     * 节流：规定在一个单位时间内，只能触发一次函数。如果这个单位时间内触发多次函数，只有一次生效。
     * @param fn 节流要执行得函数
     * @param delay 节流间隔
     * @returns {Function}
     */
    throttle(fn, delay = 500) {
        let timer = true;
        return function (args) {
            let that = this;
            let _args = arguments;
            if (!timer) {
                return false;
            }
            timer = false;
            setTimeout(() => {
                fn.apply(that, _args);
                timer = true;
            }, delay);
        };
    },

    /**
     * 随机数返回
     * @param n
     * @returns {string|string}
     */
    randomCoding(n = 6) {
        //创建26个字母数组
        let z = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; //toUpperCase() 转大写
        let Z = ["z", "b", "c", "c", "e", "f", "g", "h", "i", "j", "l", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; //toLowerCase() 转小写
        let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...z, ...Z],
            idvalue = ""; //这个值可以改变的，对应的生成多少个字母，根据自己需求所改
        for (let i = 0; i < n; i++) {
            idvalue += arr[Math.floor(Math.random() * arr.length)];
        }
        return idvalue;
    },
    /**
     * 非null,undefined和空字符以外的值
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    isExpect(value) {
        return value !== null && value !== undefined && value !== "";
    },
    /**
     * 通过链接随机的十六进制数生成一个伪GUID.
     */
    uuid() {
        var V4 = function () {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        };
        return V4() + V4() + "-" + V4() + "-" + V4() + "-" + V4() + "-" + V4() + V4() + V4();
    },
    /**
     * ES5中使用全等===会出现以下情况
     * +0 === -0 //true
     * NaN === NaN // false
     * 此方法可以弥补这个缺陷
     * @param   {Mixed}   x
     * @param   {Mixed}   y
     */
    is(x, y) {
        if (x === y) {
            // 针对+0 不等于 -0的情况
            return x !== 0 || 1 / x === 1 / y;
        }
        // 针对NaN的情况
        return x !== x && y !== y;
    },
    /**
     * 是否为整数
     *
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    isInteger(value) {
        return typeof value === "number" && isFinite(value) && value > -9007199254740992 && value < 9007199254740992 && Math.floor(value) === value;
    },
    /**
     * 是否为数字
     *
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    isNumber(value) {
        return !isNaN(value) && typeof value === "number";
    },
    /**
     * 是否为NaN
     *
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    isNaN(value) {
        return typeof value === "number" && isNaN(value);
    },

    /**
     * 是否为字符串
     *
     * @param {Mixed} str
     * @return {Boolean}
     */
    isString(value) {
        return typeof value === "string";
    },
    /**
     * 复制对象，浅拷贝
     *
     * @param {Object} obj
     * @return {Object} 返回新对象
     */
    copyObject(obj) {
        return JSON.parse(JSON.stringify(obj));
    },
    /**
     * 判断一个对象是否为Dom对象
     * @param   {Object}   obj
     * @return  {Boolean}
     */
    isDom(obj) {
        return obj && obj.nodeType === 1 && typeof obj.nodeName == "string";
    },
    /**
     * 对一个object进行深度拷贝,会将原型上的继承属性也拷贝
     * @param {*} source 需要进行拷贝的对象
     * @return {*} 拷贝后的新对象
     */
    clone(source) {
        var BUILTIN_OBJECT = {
            "[object HTMLHeadElement]": 0,
        };
        var objToString = Object.prototype.toString;

        if (typeof source == "object" && source !== null) {
            var result = source;
            if (source instanceof Array) {
                result = [];
                for (var i = 0, len = source.length; i < len; i++) {
                    result[i] = clone(source[i]);
                }
            } else if (!BUILTIN_OBJECT[objToString.call(source)] && !this.isDom(source)) {
                result = {};
                for (var key in source) {
                    result[key] = this.clone(source[key]);
                }
            }

            return result;
        }

        return source;
    },
    /**
     * 合并对象，同样属性会覆盖
     *
     * @param {Object} a
     * @param {Object} b
     * @param {Object} c
     * @return {Object}
     */
    merge() {
        var ret = {};
        for (var i = 0; i < arguments.length; i++) {
            var obj = arguments[i];
            Object.keys(obj).forEach(function (key) {
                ret[key] = obj[key];
            });
        }
        return ret;
    },
    /**
     * 将一组值转换为数组
     * @return  {Array}
     */
    arrayOf() {
        return [].slice.call(arguments);
    },
    /**
     * 数组arr是否包含给定的值value
     * @param   {Array}     arr
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    includes(arr, value) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] === value) return true;
        }
        return false;
    },
    /**
     * 判断一个字符串是否被包含在另一个字符串中
     * @param   {String}   str
     * @param   {Mixed}    value
     * @return  {Boolean}
     */
    contains(str, value) {
        return str.indexOf(value) > -1 ? true : false;
    },
    /**
     * 构造类继承关系（clazz继承于baseClazz）,原型链上的属性和方法
     * @param {Function} clazz 源类
     * @param {Function} baseClazz 基类
     */
    inherits(clazz, baseClazz) {
        var clazzPrototype = clazz.prototype;

        function F() {}
        F.prototype = baseClazz.prototype;
        clazz.prototype = new F();

        for (var prop in clazzPrototype) {
            clazz.prototype[prop] = clazzPrototype[prop];
        }
        clazz.constructor = clazz;
    },
    /**
     * 源对象的所有属性复制到目标对象，如果原对象的属性未定义（undefined），则不会复制
     * @param   {Object}       destination
     * @param   {Object}       source
     * @return  {Object}
     */
    extend(destination, source) {
        destination = destination || {};
        if (source) {
            for (var property in source) {
                var value = source[property];
                if (value !== undefined) {
                    destination[property] = value;
                }
            }
        }
        return destination;
    },
};
